package com.h5tools.ant;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore.Entry;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.json.JSONArray;
import org.json.JSONObject;

public class GenWorkspace extends Task {
	private File dir;

	private String downLoadUrl = "http://image.yihaodianimg.com/apkplugin/";

	/**
	 * the workspace dir
	 */
	public void setSrc(File f) {
		dir = f;
	}


	@Override
	public void execute() throws BuildException {
		if (dir == null) {
			throw new BuildException("src is missing");
		}
		if (!dir.isDirectory()) {
			throw new BuildException(dir + " is not a directory");
		}

		HashMap<String, JSONObject> files = new HashMap<String, JSONObject>();
		HashMap<String, JSONObject> fragments = new HashMap<String, JSONObject>();
		File output = new File(dir, "bin");
		output.mkdirs();
		File apk = new File(output, "pluginback");
		File apkrelease = new File(output,"plugin");
		if(!apk.exists())
		{
			apk.mkdir();
		}
		if(!apkrelease.exists())
		{
			apkrelease.mkdir();
		}
		Map<String,String> apknameContainer = new HashMap<String, String>();
		for (File proj : dir.listFiles()) {
			File bin = new File(proj, "bin");
			File site = new File(bin, "site.txt");
			if (!site.isFile())
				continue;

			System.out.println(proj.getName());
			try {
				FileInputStream fis = new FileInputStream(site);
				byte[] bytes = new byte[fis.available()];
				fis.read(bytes);
				fis.close();

				String str = new String(bytes, "utf-8");
				JSONObject j = new JSONObject(str);
				JSONArray siteFiles = j.getJSONArray("files");
				for (int i = 0; i < siteFiles.length(); i++) {
					JSONObject file = siteFiles.getJSONObject(i);
					/*yht*/
					String fname = file.getString("name");
					String apkName = String.format("%s.apk", fname);
					File releaseFile = new File(apkrelease,apkName);
					File orginApk = new File(bin,apkName);
					SimpleDateFormat bkfmt = new SimpleDateFormat("yyyyMMddHHmmss");
					String pluginBack = String.format("%s%s.apk", fname,bkfmt.format(new Date()));
					apknameContainer.put(fname, pluginBack);
					File bkFile = new File(apk,pluginBack);;
					this.copyFileTo(orginApk, releaseFile);
					this.copyFileTo(orginApk, bkFile);
					/*yht*/
					//String id = file.getString("id");
					JSONObject old = files.get(fname);
					if (old == null) {
						// project path -> workspace path
						String url = file.getString("url");
						if (url.startsWith("file://")) {
							File path = new File(proj, url.substring("file://"
									.length()));
							File rel = GenSite.getRelativeFile(path, dir);
							file.put("url", "file://" + rel);
						}
						files.put(fname, file);
					} else {
						String md5a = file.getString("md5");
						String md5b = old.getString("md5");
						if (!md5a.equals(md5b)) {
							// break
							throw new BuildException("md5 conflict for file "
									+ fname + " in " + proj.getName());
						}
					}
				}
				JSONArray siteFragments = j.getJSONArray("fragments");
				for (int i = 0; i < siteFragments.length(); i++) {
					JSONObject fragment = siteFragments.getJSONObject(i);
					String host = fragment.getString("host");
					JSONObject old = fragments.get(host);
					if (old == null) {
						fragments.put(host, fragment);
					} else {
						// continue;
						System.out.println("override " + host + " as "
								+ proj.getName() + "/"
								+ fragment.getString("name"));
						fragments.put(host, fragment);
					}
				}
			} catch (BuildException e) {
				throw e;
			} catch (Exception e) {
				System.out.println("fail to open " + site);
				e.printStackTrace(System.err);
			}
		}
		try {
			JSONObject json = new JSONObject();
			JSONObject serverjson = new JSONObject();
			SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
			String today = fmt.format(new Date());
			json.put("id", "all." + today + ".0");
			json.put("version", today + ".0");
			serverjson.put("id", "all." + today + ".0");
			serverjson.put("version", today + ".0");
			System.out.println("site.txt id=all." + today + ".0");

			JSONArray siteFiles = new JSONArray();
			for (JSONObject file : files.values()) {
				siteFiles.put(file);
			}
			json.put("files", siteFiles);

			JSONArray siteFragments = new JSONArray();
			for (JSONObject fragment : fragments.values()) {
				siteFragments.put(fragment);
			}
			json.put("fragments", siteFragments);


			File site_output = new File(output, "site.txt");
			File site_server = new File(output,"server.txt");
			FileOutputStream fos = new FileOutputStream(site_output);
			fos.write(json.toString(2).getBytes("ASCII"));
			fos.close();
			/*yht 生成site_server.txt*/
			if(site_server.exists())
			{
				JSONObject old = new JSONObject(readTxtFile(site_server));
				JSONArray old_file = old.getJSONArray("files");
				//Map<String,JSONObject> oldfmap = new HashMap<String, JSONObject>();
				for(int i=0;i<old_file.length();i++)
				{
					JSONObject oldtp = old_file.getJSONObject(i);
					//oldfmap.put(tp.getString("name"), tp);
					String tpname = oldtp.getString("name");
					if(files.containsKey(tpname))
					{
						JSONObject newtp = files.get(tpname);
						if(oldtp.getString("md5").equals(newtp.getString("md5")))
						{
							String newId= newtp.getString("id");
							String oldId = oldtp.getString("id");
							System.out.println(String.format("newid:%s,oldid:%s",newId,oldId));
							//没更新,服务器端使用旧版文件
							newtp.put("id", oldId);
							//更新url为下载地址
							//newtp.put("url", String.format("%s%s", downLoadUrl,apknameContainer.get(tpname)));
							newtp.put("url", oldtp.getString("url"));
							File tobedel = new File(apk,apknameContainer.get(tpname));
							//不需要发布，删除这次发布的文件
							if(tobedel.exists())
							{
								tobedel.delete();
							}
							//files.put(tpname, newtp);
							ArrayList<String> fkey = new ArrayList<String>();//值为host
							for(java.util.Map.Entry<String, JSONObject> fragtp : fragments.entrySet())
							{
								if(fragtp.getValue().getString("code").equals(newId))
								{
									fkey.add(fragtp.getKey());
								}
							}
							//执行替换操作
							for(String fk : fkey)
							{
								//fragments.put
								JSONObject tobereplace = fragments.get(fk);
								tobereplace.put("code", oldId);
								//fragments.put(fk, tobereplace);
							}
						}
						else
						{
							//更新过的文件更新为x新的url
							newtp.put("url", String.format("%s%s", downLoadUrl,apknameContainer.get(tpname)));
						}
					}
				}
				JSONArray siteFiles_server = new JSONArray();
				for (JSONObject file : files.values()) {
					//file.put("url", String.format("%s%s", downLoadUrl,apknameContainer.get(file.getString("name"))));
					siteFiles_server.put(file);
				}
				serverjson.put("files", siteFiles_server);
			}
			else
			{
				//替换成链接
				JSONArray siteFiles_server = new JSONArray();
				for (JSONObject file : files.values()) {
					file.put("url", String.format("%s%s", downLoadUrl,apknameContainer.get(file.getString("name"))));
					siteFiles_server.put(file);
				}
				serverjson.put("files", siteFiles_server);
			}

			JSONArray siteFragments_server = new JSONArray();
			for (JSONObject fragment : fragments.values()) {
				siteFragments_server.put(fragment);
			}
			serverjson.put("fragments", siteFragments_server);
			FileOutputStream fos_server = new FileOutputStream(site_server);
			fos_server.write(serverjson.toString(2).getBytes("ASCII"));
			fos_server.close();
			/*yht 生成site_server.txt*/
			System.out.println(output);
		} catch (Exception e) {
			throw new BuildException("unable to build site.txt:---"+e.getStackTrace().toString());
		}
	}

	private boolean copyFileTo(File srcFile, File destFile) throws IOException {  
		if (srcFile.isDirectory() || destFile.isDirectory())  
			return false;// 判断是否是文件  
		FileInputStream fis = new FileInputStream(srcFile);  
		FileOutputStream fos = new FileOutputStream(destFile);  
		int readLen = 0;  
		byte[] buf = new byte[1024];  
		while ((readLen = fis.read(buf)) != -1) {  
			fos.write(buf, 0, readLen);  
		}  
		fos.flush();  
		fos.close();  
		fis.close();  
		return true;  
	}  
	public void DeleteFile(File file,boolean delself) { 
		if (file.exists() == false) { 
			return; 
		} else { 
			if (file.isFile()) { 
				file.delete(); 
				return; 
			} 
			if (file.isDirectory()) { 
				File[] childFile = file.listFiles(); 
				if (childFile == null || childFile.length == 0) {
					if(delself)
					{
						file.delete(); 
					}
					return; 
				} 
				for (File f : childFile) { 
					DeleteFile(f,true); 
				} 
				if(delself)
				{
					file.delete(); 
				}
				//file.delete(); 
			} 
		}
	}

	/*
	 * 从文本文件读取文本
	 */
	private String readTxtFile(File f)
	{
		try{ 
			FileInputStream in = new FileInputStream(f); 
			byte[]data = read2byte(in); 
			in.close();
			return new String(data,"UTF-8"); 
		} 
		catch(Exception e){ 
			return "";
		} 
	}

	private byte[] read2byte(InputStream in) throws IOException { 
		byte[] data; 
		ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
		byte[]buf = new byte[1024]; 
		int len = 0; 
		while((len = in.read(buf))!=-1){ 
			bout.write(buf, 0, len); 
		} 
		data = bout.toByteArray(); 
		bout.close();
		return data; 
	} 
}
